package com.bosssoft.user.permission.center.serve.service.impl;

import com.bosssoft.user.permission.center.serve.dao.entity.BasicRole;
import com.bosssoft.user.permission.center.serve.dao.entity.BasicUser;
import com.bosssoft.user.permission.center.serve.dao.entity.TreeNode;
import com.bosssoft.user.permission.center.serve.dao.mapper.BasicRoleMapper;
import com.bosssoft.user.permission.center.serve.dao.mapper.BasicUserMapper;
import com.bosssoft.user.permission.center.serve.dao.mapper.ResourceMapper;
import com.bosssoft.user.permission.center.serve.pojo.dto.*;
import com.bosssoft.user.permission.center.serve.pojo.query.LoginQuery;
import com.bosssoft.user.permission.center.serve.service.LoginService;
import com.bosssoft.user.permission.center.serve.util.LoginTokenUtil;
import common.annotation.ApiLog;
import common.exception.code.BizErrorCode;
import common.exception.parse.BusinessException;
import common.util.MyBeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import static org.apache.commons.codec.digest.DigestUtils.md5Hex;

/**
 * @className: LoginServiceImpl
 * @description: 登录业务的具体实现
 * @author: lanyukai
 * @date: 2024/6/11 17:06
 * @since 1.0
 **/
@Validated
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {
    /**
     * 用于操作用户基本数据
     */
    @Resource
    private BasicUserMapper basicUserMapper;
    /**
     * 操作角色数据
     */
    @Resource
    private BasicRoleMapper basicRoleMapper;
    @Resource
    private ResourceMapper resourceMapper;

    /**
     * 使用MD5加密密码
     * @author lanyukai
     * @date 2024/06/18 10:29
     * @param password 密码
     * @return 加密后的密码
     */
    public String encodePasswordWithMD5(String password){
        return md5Hex(password);
    }
    /**
     * 生成DTO
     * @author lanyukai
     * @date 2024/06/12 17:13
     * @param basicUser 用户信息
     * @return 生成的DTO
     */
    public LoginDTO createLoginDTO(BasicUser basicUser){
        LoginDTO loginDTO = MyBeanUtil.copyProperties(basicUser, LoginDTO::new);
        // 设置角色列表
        List<BasicRole> roleList = basicRoleMapper.selectRoleListByUserId(basicUser.getId());
        List<LoginRoleDTO> roleDTOList = new ArrayList<>();
        for(BasicRole basicRole : roleList){
            roleDTOList.add(new LoginRoleDTO(basicRole.getId(), basicRole.getName()));
        }
        loginDTO.setRoleList(roleDTOList);
        return loginDTO;
    }

    /**
     * 通过角色列表获取主菜单树的set集合,并且去重
     * @author lanyukai
     * @date 2024/06/17 14:51
     * @param loginRoleDTOList 角色列表
     * @return 去重后的主菜单树的set集合
     */
    public List<RouteMainMenuDTO> getTreeNodeListByRoleIds(List<LoginRoleDTO> loginRoleDTOList){
        HashSet<TreeNode> mainMenus = new HashSet<>();
        for(LoginRoleDTO loginRoleDTO : loginRoleDTOList){
            mainMenus.addAll(resourceMapper.selectTreeNodesByRoleId(loginRoleDTO.getId()));
        }
        return MyBeanUtil.copyList(new ArrayList<>(mainMenus), RouteMainMenuDTO::new, null);
    }
    /**
     * 将节点、子菜单赋予主菜单,深度3层
     * @author lanyukai
     * @date 2024/06/18 09:55
     * @param mainMenus 主菜单
     * @return 是否赋予成功
     */
    public Boolean addNodesToMenus(List<RouteMainMenuDTO> mainMenus){
        for(RouteMainMenuDTO mainMenu : mainMenus){
            List<TreeNode> subMenus = resourceMapper.selectSubTreeNodeByParentId(mainMenu.getId());
            mainMenu.setNodes(MyBeanUtil.copyList(subMenus, RouteSubMenuDTO::new, null));
            for(RouteSubMenuDTO subMenu : mainMenu.getNodes()){
                List<com.bosssoft.user.permission.center.serve.dao.entity.Resource> nodes =
                        resourceMapper.selectResourceByParentId(subMenu.getId());
                subMenu.setNodes(MyBeanUtil.copyList(nodes, RouteNodeDTO::new, null));
            }
        }
        return Boolean.TRUE;
    }

    @ApiLog
    @Override
    public LoginDTO login(@NotNull @Valid LoginQuery loginQuery) {
        //加密密码
        loginQuery.setPassword(encodePasswordWithMD5(loginQuery.getPassword()));
        //查找指定用户
        BasicUser basicUser = basicUserMapper.selectBasicUserByCodeAndPasswordAndTenantAccount(loginQuery.getCode(), loginQuery.getPassword(), loginQuery.getTenantCode());
        //检查是否查询到指定用户信息
        if(basicUser == null){
            throw new BusinessException(BizErrorCode.DATA_SEARCH_NOT_FOUND, "找不到指定用户");
        }
        //校验通过, 调用token生成函数，生成token并返回给控制层
        return createLoginDTO(basicUser);
    }

    @ApiLog
    @Override
    public RouteDTO createDynamicRoute() {
        //取出token中的角色列表信息
        LoginDTO loginDTO = LoginTokenUtil.parseTokenToLoginDTO();
        List<LoginRoleDTO> loginRoleDTOList = loginDTO.getRoleList();
        if(loginRoleDTOList == null || loginRoleDTOList.isEmpty()){
            throw new BusinessException(BizErrorCode.DATA_SEARCH_NOT_FOUND, "找不到指定角色");
        }
        //获取主菜单
            List<RouteMainMenuDTO> mainMenus = getTreeNodeListByRoleIds(loginRoleDTOList);
        //将从菜单树赋予主菜单
        if(!addNodesToMenus(mainMenus)){
            throw new BusinessException(BizErrorCode.UNDEFINED, "赋予菜单使发生未知异常");
        }
        //返回路由表
        return new RouteDTO(mainMenus);
    }
}
